



\chapter{后端系统-校园活动管理}

\section{系统架构}

本后端系统使用spring boot + spring security，并使用JPA进行数据持久化。借鉴于MVC架构将代码按照不同的功能分层，并将主要代码逻辑划分为三层：

\begin{itemize}
\item Controller层：controller包。

  该层负责与前端交互。定义了所有接口的请求方式，URL，请求体和返回格式。

\item Service层: service包。

  该层负责处理系统的业务逻辑。

\item Repository层: entity包，repository包

  该层负责创建和操作数据库。

\item component包为工具包。

  该层内有几个工具类，服务于Service层和其他工具类。

\item security包为Jwt鉴权相关类

  该包负责生成token，认证，鉴权，以及拦截请求中的token

\begin{center}
    \includegraphics[height=0.8\textheight]{/后端总体架构.png}
\end{center}

\end{itemize}
\section{详细设计}

\subsection{接口设计}


统一返回格式，以下所有接口返回格式只包含result的结果：

\begin{lstlisting}
{
    error_code:0,//0为成功，失败则返回-1,-2等
    error_msg:"message",//成功时为成功信息，失败时为失败原因
    result: <Anything>
}
\end{lstlisting}

\subsubsection{user}

\paragraph{POST /login}~{}

用户登录

\begin{itemize}
\item 请求体

\begin{lstlisting}
{
    "account": "账号",
    "password": "密码",
    "wxcode":"Wx.login返回的code"
}
\end{lstlisting}

\item 返回

\begin{lstlisting}
{
    "id": "用户id",
    "token": "token"
}
\end{lstlisting}

\end{itemize}
\paragraph{Post /users}~{}

用户注册

\begin{itemize}
\item 请求体：

\begin{lstlisting}
{
    "userName": "用户名",
    "userNumber": "学号",
    "phoneNumber": "电话",
    "age": "年龄",
    "gender":"性别",
    "avatar": "头像"
}
\end{lstlisting}

\item 返回

\begin{lstlisting}
  {
  	"id":用户id
  }
\end{lstlisting}

  

\end{itemize}
\paragraph{Get /users/\{id\}}~{}

根据id请求用户信息

\begin{itemize}
\item 参数

\item id 用户id

\item 返回

\begin{lstlisting}
   {
   	"id": "用户id", (long)
   	"userName": "用户名",
   	"userNumber": "学号/工号",
   	"phoneNumber": "电话",
   	"age":"年龄", (long)
   	"gender": "性别",
   	"avater":"头像"
   }
\end{lstlisting}



\end{itemize}
\paragraph{Put /users/\{id\}}~{}

修改用户信息

\begin{itemize}
\item 参数

\begin{itemize}
\item id 用户id

\end{itemize}
\item 请求体（同注册）

\begin{lstlisting}
   {
       "userName": "用户名",
       "userNumber": "学号",
       "phoneNumber": "电话",
       "age": "年龄",
       "gender":"性别",
       "avatar": "头像"
   }
\end{lstlisting}



\end{itemize}
\paragraph{POST /users/\{id\}/avatar?file=\{picData\}}~{}

上传头像

\begin{itemize}
\item 参数

\begin{itemize}
\item id 用户id

\end{itemize}
\item 返回

\begin{lstlisting}
   "pictureUrl"
\end{lstlisting}

   

\end{itemize}
\paragraph{Get /users/\{id\}/joined?state=\{state\}}~{}

获取id用户参加的所有活动

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 用户id
\item state 希望查询的状态 (passing/passed/deny/default)

\end{itemize}
\item 返回

\begin{lstlisting}
   [
       {
           "activityInfo":{
               "activityId": "活动id",
               "activityName": "活动名称",
               "activityLocation": "活动地点",
               "activityStart": "活动开始时间", //long
               "activityEnd": "活动结束时间", //long
               "activityProfile": "活动简介",
               "activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
               "activityPic": "活动图片",
               "joinNum": "活动参与人数", //int
               "publisherId": "活动发布者id"
           },
           "passed": "参与活动申请状态" //true->申请成功 false->申请失败 null->等待活动发布者审核
       }
   ]
\end{lstlisting}



\end{itemize}
\paragraph{Get /users/\{id\}/published?state=\{state\}}~{}

获取id用户发布的所有活动

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 用户id
\item state 希望查询的状态 (checking/checked/deny/default)

\end{itemize}
\item 返回

\begin{lstlisting}
   [
       {
           "activityInfo":{
               "activityId": "活动id",
               "activityName": "活动名称",
               "activityLocation": "活动地点",
               "activityStart": "活动开始时间", //long
               "activityEnd": "活动结束时间", //long
               "activityProfile": "活动简介",
               "activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
               "activityPic": "活动图片",
               "joinNum": "活动参与人数", //int
               "publisherId": "活动发布者id"
           },
           "checked": "参与活动申请状态" //true->通过审核 false->未通过审核 null->等待管理员审核
       }
   ]
\end{lstlisting}

   

\end{itemize}
\paragraph{GET /users/\{id\}/message?state=\{state\}}~{}

获取发布者发布的所有活动的申请信息

\begin{itemize}
\item 参数
\begin{itemize}
\item id：发布者id
\item state
\begin{itemize}
\item passing
\item passed
\item deny

\end{itemize}
\item 返回

\begin{lstlisting}
[{
  "userInfo": {
    "id": "用户id",(long)
    "userName": "用户名",
    "userNumber": "学号/工号",
    "phoneNumber": "电话",
    "age": "年龄",(long)
    "gender": "性别",
    "avater": "头像"
  },
  "activityInfo": {
    "activityId": "活动id",
    "activityName": "活动名称",
    "activityLocation": "活动地点",
    "activityStart": "活动开始时间", //long
    "activityEnd": "活动结束时间", //long
    "activityProfile": "活动简介",
    "activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
    "activityPic": "活动图片",
    "joinNum": "活动参与人数", //int
    "publisherId": "活动发布者id"
  }
}]
\end{lstlisting}



\end{itemize}
\end{itemize}
\paragraph{GET /users/\{id\}/sign?state=\{state\}}~{}

获取某用户签到的活动

\begin{itemize}
\item 参数
\begin{itemize}
\item id: 用户id
\item state  Boolean true -> 已签到 false -> 未签到
\end{itemize}
\item 返回

\begin{lstlisting}
[{
	"activityId": "活动id",
	"activityName": "活动名称",
	"activityLocation": "活动地点",
	"activityStart": "活动开始时间", //long
	"activityEnd": "活动结束时间", //long
	"activityProfile": "活动简介",
	"activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
	"activityPic": "活动图片",
	"joinNum": "活动参与人数", //int
    "publisherId": "活动发布者id"
}]
\end{lstlisting}



\end{itemize}
\paragraph{PUT /users/\{userId\}/sign/\{activityId\}}~{}

用户签到

\begin{itemize}
\item 参数
\begin{itemize}
\item userId 用户id
\item activityId 活动id



\end{itemize}
\end{itemize}
\paragraph{PUT /users/\{userId\}/pass/\{activityId\}?state=\{state\}}~{}

发起者审批是否同意某人参与活动的申请

\begin{itemize}
\item 参数
\begin{itemize}
\item state 审批结果 true -> 同意 false -> 拒绝



\end{itemize}
\end{itemize}
\paragraph{PUT /users/\{id\}/bind?code=\{code\}}~{}

绑定某用户的微信账号

\begin{itemize}
\item 参数
\begin{itemize}
\item id: 用户id
\item code: 前端通过调用wx.login获取的code





\end{itemize}
\end{itemize}
\subsubsection{Activity}

\paragraph{Get /activities/\{id\}}~{}

根据活动id获取活动信息

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 活动id

\end{itemize}
\item 返回

\begin{lstlisting}
   {
   	"activityId": "活动id",
   	"activityName": "活动名称",
   	"activityLocation": "活动地点",
   	"activityStart": "活动开始时间", //long
   	"activityEnd": "活动结束时间", //long
   	"activityProfile": "活动简介",
   	"activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
   	"activityPic": "活动图片",
   	"joinNum": "活动参与人数", //int
       "publisherId": "活动发布者id"
   }
\end{lstlisting}



\end{itemize}
\paragraph{Get /activities/\{id\}/joiners\&page=\{page\}\&size=\{size\}}~{}

查看某活动的所有参与者

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 活动id
\item page: 页码
\item size: 每页大小

\end{itemize}
\item 返回

\begin{lstlisting}
   {
       "id": "用户id",
       "userName": "用户名",
       "userNumber": "学号",
       "phoneNumber": "电话",
       "age": "年龄",
       "gender":"性别",
       "avatar": "头像"
   }
\end{lstlisting}



\end{itemize}
\paragraph{Post /activities/\{activityId\}/joiners/\{userId\}}~{}

为某活动添加一条参与申请

\begin{itemize}
\item 参数
\begin{itemize}
\item activityId: 活动id
\item userId: 参与者id



\end{itemize}
\end{itemize}
\paragraph{Get /activities/home?order=\{order\}\&page=\{page\}\&size=\{size\}}~{}

提供主页活动推荐

\begin{itemize}
\item 参数

\begin{itemize}
\item order: 排序方式 （default/hotest/latest）//目前hotest未实现
\item page: 页码
\item size: 每页大小

\end{itemize}
\item 返回

\begin{lstlisting}
   [
   	{
   		"activityId": "活动id",
   		"activityName": "活动名称",
   		"activityLocation": "活动地点",
   		"activityStart": "活动开始时间", //long
   		"activityEnd": "活动结束时间", //long
   		"activityProfile": "活动简介",
   		"activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
   		"activityPic": "活动图片",
   	  	"joinNum": "活动参与人数", //int
     	    "publisherId": "活动发布者id"
   	}
   ]
\end{lstlisting}



\end{itemize}
\paragraph{Get /activities}~{}

根据名字检索活动

\begin{itemize}
\item 参数

\begin{itemize}
\item name: "活动名称"

\end{itemize}
\item 返回（同上）

\begin{lstlisting}
   [
   	{
   		"activityId": "活动id",
   		"activityName": "活动名称",
   		"activityLocation": "活动地点",
   		"activityStart": "活动开始时间", //long
   		"activityEnd": "活动结束时间", //long
   		"activityProfile": "活动简介",
   		"activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
   		"activityPic": "活动图片",
   		"joinNum": "活动参与人数", //int
     	    "publisherId": "活动发布者id"
   	}
   ]
\end{lstlisting}



\end{itemize}
\paragraph{Post /activities}~{}

添加活动

\begin{itemize}
\item 参数

\begin{itemize}
\item 请求体

\begin{lstlisting}
    {
    	"activityName": "活动名称",
        "activityProfile": "活动简介",
        "activityStart": "开始时间",
        "activityEnd": "结束时间",
        "activityKind": "活动类别", //枚举类
        "activityLocation": "活动地点",
        "activityPic": "活动图片",
        "publisherId": "活动发布者id"
        
    }
\end{lstlisting}



\end{itemize}
\end{itemize}
\paragraph{Put /activities/\{id\}}~{}

修改活动信息

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 活动id

\item 请求体（同上）

\begin{lstlisting}
    {
    	"activityName": "活动名称",
        "activityProfile": "活动简介",
        "activityStart": "开始时间",
        "activityEnd": "结束时间",
        "activityKind": "活动类别", //枚举类
        "activityLocation": "活动地点",
        "activityPic": "活动图片"
    }
\end{lstlisting}



\end{itemize}
\end{itemize}
\paragraph{GET /activities/\{id\}/sign}~{}

获取某活动签到的参与者

\begin{itemize}
\item 参数
\begin{itemize}
\item id: 活动id
\item state Boolean ture ->已签到 false -> 未签到

\end{itemize}
\item 返回

\begin{lstlisting}
[{
    "id": "用户id",(long)
    "userName": "用户名",
    "userNumber": "学号/工号",
    "phoneNumber": "电话",
    "age": "年龄",(long)
    "gender": "性别",
    "avater": "头像"
}]
\end{lstlisting}

\end{itemize}
\paragraph{POST /activities/\{id\}/banner?file=\{picData\}}~{}

上传活动图片

\begin{itemize}
\item 参数

\begin{itemize}
\item id: 活动id

\end{itemize}
\item 返回

\begin{lstlisting}
    "pictureUrl"
\end{lstlisting}

\end{itemize}
\subsubsection{ADMIN}

\paragraph{GET /admins/\{id\}/check?state=\{state\}\&page=\{page\}\&size=\{size\}}~{}

管理员获取自己需要审批的活动

\begin{itemize}
\item 参数
\begin{itemize}
\item id: 管理员id
\item state: 审批状态 null -> 未审核 true -> 通过 false -> 审核未通过
\end{itemize}
\item 返回

\begin{lstlisting}
[
	{
		"activityId": "活动id",
		"activityName": "活动名称",
		"activityLocation": "活动地点",
		"activityStart": "活动开始时间", //long
		"activityEnd": "活动结束时间", //long
		"activityProfile": "活动简介",
		"activityKind": "活动类型", //枚举类：STUDY,PLAY,SPORTS,READING,OTHERS
		"activityPic": "活动图片",
		"joinNum": "活动参与人数", //int
  	    "publisherId": "活动发布者id"
	}
]
\end{lstlisting}



\end{itemize}
\paragraph{PUT /admins/\{activityId\}?state=\{state\}}~{}

管理员审批活动

\begin{itemize}
\item 参数
\begin{itemize}
\item activityId: 审批的活动id
\item state: 审批结果 true->通过 false->不通过 null->更改未待审核状态(最好不要使用)

\end{itemize}
\end{itemize}
\subsection{Service层设计}

该层负责处理系统的业务逻辑，根据操作的业务对象进行划分，生成几个Service类，处理不同方面的逻辑。例如：ActivityService（处理活动相关逻辑）,UserService（处理用户相关逻辑）,UdrService（处理用户与身份关联逻辑）,RoleService（管理系统内出现的所有身份）,SignUpActivityService（管理活动报名与签到），RSAService（提供RSA解密服务，解密前端传来的密码。因为前端使用RSA加密密码，防止密码明文在网络环境中传输）

该层对每一个Service类都定义了相应的接口，规范了实现类应有的操作，并方便进行逻辑的替换，如需以不同的方式实现逻辑，只需写一个新类继承该接口，在依赖注入时替换掉旧类。

其中第三方登录的逻辑较为复杂，画出流程图如下：

\begin{itemize}
\item 登录流程图

\begin{center}
    \includegraphics[height=0.8\textheight]{/登录流程图.png}
\end{center}



\item 绑定微信流程图

\begin{center}
    \includegraphics[height=0.8\textheight]{/绑定微信账号流程图.png}
\end{center}

\end{itemize}
\subsection{数据库设计}

在项目中使用spring JPA的注解@Entity来创建数据库，并使用@Repository注解来提供对数据库的操作。

对本系统的业务逻辑进行分析，需要持久化存储的信息有：用户信息、活动信息、报名信息。因为要管理员审核活动，所以还需要身份信息。综上，我们需要建立如下几个table:

\subsubsection{tb\_user 用户表}

\begin{center}
    \resizebox{\textwidth}{!}{
        \begin{tabular}{|p{3em}|p{5em}|p{3em}|p{6em}|p{14em}|p{3em}|p{7em}|p{5em}|p{6em}|p{5em}|}
            \hline
 id & user\_age & avatar & user\_gender & last\_password\_reset\_date & pwd & phone\_number & user\_name & user\_number & wx\_openid \\
\hline


 id & 用户年龄 & 头像uri & 用户性别 & 上一次修改密码的时间 & 密码 & 手机号(账号) & 昵称 & 学号/工号 & 微信官方提供的用户唯一标识 \\
\hline

 \end{tabular}
    }
\end{center}

\subsubsection{tb\_activity 活动表}

\begin{center}
    \resizebox{\textwidth}{!}{
        \begin{tabular}{|p{3em}|p{4em}|p{4em}|p{3em}|p{5em}|p{7em}|p{6em}|p{3em}|p{6em}|p{7em}|p{4em}|p{6em}|p{7em}|}
            \hline
 id & a\_code & a\_name & a\_pic & a\_profile & activity\_type & is\_checked & a\_end & a\_location & publish\_time & a\_start & examiner\_id & publisher\_id \\
\hline


 id & 活动码 & 活动名称 & 活动图片uri & 活动简介 & 活动类型 & 标识活动是否通过管理员审核 & 活动结束时间 & 活动地点 & 活动发布时间 & 活动开始时间 & 审核该活动的管理员id & 活动发布者id \\
\hline

 \end{tabular}
    }
\end{center}

\subsubsection{tb\_signup\_activity 活动申请与签到表}

\begin{center}
        \begin{tabularx}{\textwidth}{|*{5}{X|}}
            \hline
 id & activity\_id & is\_passed & is\_signed & user\_id \\
\hline


 id & 活动id & 标识此条申请是否被发布者通过 & 标识是否签到 & 参与者id \\
\hline

 \end{tabularx}
\end{center}

\subsubsection{auth\_role 角色表}

\begin{center}
        \begin{tabularx}{\textwidth}{|*{2}{X|}}
            \hline
 id & type \\
\hline


 0 & ROLE\_DEFAULT \\
\hline

 1 & ROLE\_ADMIN \\
\hline

 \end{tabularx}
\end{center}

\subsubsection{auth\_r\_user\_role 用户角色表}

\begin{center}
        \begin{tabularx}{\textwidth}{|*{4}{X|}}
            \hline
 id & note & role\_id & user\_id \\
\hline


 id & 标签 & 角色id & 用户id \\
\hline

 \end{tabularx}
\end{center}



\subsection{Component包}

	该包包含各种工具类。包括配置spring和支持Service层的某些通用功能。

\subsubsection{ApplicationStartUp}

	该类继承自springframework提供的ApplicationListener，对ContextRefreshedEvent事件进行监听。实现当服务器启动时，向数据库中插入一些必要的值，如：管理员账号，身份信息。

\subsubsection{ServerConfig}

	该类会获取配置文件中的信息，当其他类需要读取配置文件中的值时，只需要注入该类即可。这样可以在某个类需要配置文件中的属性时免去查看配置信息的麻烦。

\subsubsection{RSAUtil}

	该类是提供RSA算法的工具类。前端返回的密码是使用RSA公钥加密过的密文，需要后端使用RSA密钥进行解密。

\subsubsection{WebSecurity}

	该类保障服务器的接口安全，继承自WebSecurityConfigurerAdapter类。配置了后端的认证方式，密码的加密算法，token的过滤方式以及接口的访问权限。

\subsubsection{LoggingFilterConfig}

	拦截所有的请求和响应报文，并打印。便于调试。

\subsection{security包}

	该包为系统安全相关的类，主要功能包括认证、鉴权和token的相关操作。

\subsubsection{JwtTokenUtil}

	该类提供Token的相关操作，包括token的生成，token的解析，token的有效性判断。

	在该系统中需要有两种类型的Token，一种是普通的登录方式，由手机号密码登录产生的token。一种是微信第三方登录产生的Token。之所以需要两种token，是因为在产生Token之前，会先对手机号和密码进行认证（保证产生的token是正确的），此时是需要密码明文的。而使用第三方登录时，可以从第三方获取到用户唯一标识，并根据该标识查找数据库中该用户的信息。但是为了安全，数据库中存储的密码是经过BCrypt加密过的密文，该加密算法为单向加密，无法获取密码明文，也就无法在生成Token前进行认证。所以第三方生成的token需要跳过改认证阶段，为了区分就标记为两种类型，其中第三方登录的token会包含微信第三方的用户标识。

\subsubsection{JwtUser}

	实现UserDetails接口，提供认证所需的账号密码，鉴权所需的身份信息。以及其他附属信息，如为了支持第三方增加的openId，标记用户的id，和密码的最近修改日期。

	该类的用户名、密码等信息依赖于数据库中的User表。JwtUser是为了实现认证、鉴权功能而单独建立的用户类，与原本系统中的User耦合度很低。

\subsubsection{JwtUserDetailsServiceImpl}

	实现UserDetailsService接口，可以通过账号查找User和他相应的身份信息，并通过JwtUserFactory生成JwtUser。

\subsubsection{JwtUserFactory}

	生成JwtUser类的工厂，通过用户信息User和用户身份信息List\<Role>创建。

\subsubsection{JwtAuthenticationTokenFilter}

	继承自OncePerRequestFilter类，在WebSecurity类中加入到spring的Filter框架中。该类实现了对每一条请求的过滤，会从请求信息中拿到Token，并使用JwtUtil进行认证。

\begin{itemize}
\item 通过spring的filter过滤链，实现AOP。达到对所有接口进行过滤，进行token认证的目的。

\begin{center}
    \includegraphics[height=0.8\textheight]{/filter.jpg}
\end{center}

\item token认证鉴权流程图

\begin{center}
    \includegraphics[height=0.8\textheight]{/token认证流程.png}
\end{center}

\end{itemize}
\subsection{主要功能}

\subsubsection{Repository层}

将数据库中的表与@Entity实体类关联，并且提供数据库操作。

以下没有显式说明的，即已包含JPA自带的方法，如findById()，delete()等

\begin{itemize}
\item ActivityRepository

  提供对Activity活动的数据库操作，包含但不限于

\begin{itemize}
\item 根据活动码查找活动
\item 根据活动名称模糊查找活动
\item 根据活动类型查找活动
\item 查找所有已经通过管理员审核的活动
\item 查找所有未通过管理员审核的活动
\item 查找所有尚未审核的活动
\item 查找某用户发布的活动
\item 查找某用户发布的未通过审核的活动
\item 查找某用户发布的已通过审核的活动
\item 查找某用户发布的尚未审核的活动
\item 查找某管理员审核的活动
\item 查找某管理员审核未通过的活动
\item 查找某管理员已经审核通过的活动
\item 查找某管理员还未审核的活动

\end{itemize}
\item UserRepository

  提供对User用户信息的数据库操作，包含但不限于

\begin{itemize}
\item 根据活动查找该活动的发布者
\item 根据活动查找该活动的审核者

\end{itemize}
\item SignUpActivityRepository

  提供对用户申请活动和签到信息的数据库操作，包含但不限于

\begin{itemize}
\item 根据参与者id查找
\item 根据活动id查找
\item 根据参与者id和活动id查找
\item 查找已经通过活动发起者审核的表项
\item 查找未通过活动发起者审核的表项
\item 查找某参与者已经通过发起者审核的表项
\item 查找某参与者未通过发起者审核的表项
\item 查找某参与者正在等待审核的表项
\item 查找某活动已经通过审核的参与者的表项
\item 查找某活动未审核的参与者的表项
\item 查找某活动正在等待审核中的参与者的表项
\item 查找某活动未签到的表项
\item 查找活动已签到的表项
\item 查找某用户未签到的表项
\item 查找某用户已签到的表项

\end{itemize}
\item RoleRepository

  提供对于Role角色的数据库操作，包含但不限于

\begin{itemize}
\item 按照角色名称查找

\end{itemize}
\item UdrRepository

  提供对于用户角色权限Udr的数据库操作，包含但不限于

\begin{itemize}
\item 按照用户id查找
\item 按照用户角色查找

\end{itemize}
\end{itemize}
\subsubsection{Service层}

\textbf{为了利于日后更新，满足OCP，Service层采用设置接口，并使用实现类实现接口的方式。}

\begin{itemize}
\item ActivityService

\begin{itemize}
\item 发布活动
\item 修改活动信息
\item 删除活动
\item 管理员提交审核结果
\item 获取所有活动
\item 根据活动类型查找活动
\item 根据活动名称查找活动
\item 根据活动主键查找活动
\item 根据活动审核状态查找活动
\item 查找某一发布者发布的活动
\item 查找某一管理员的审核活动记录

\end{itemize}
\item SignUpActivityService

\begin{itemize}
\item 查找某一用户报名参与的活动
\item 活动发布者查看某一活动有哪些人报名
\item 报名参与活动
\item 是否同意参与活动的申请
\item 是否同意参与活动的所有申请
\item 获取某活动签到的用户
\item 获取某用户签到的活动
\item 签到活动

\end{itemize}
\item UserService

\begin{itemize}
\item 手机号密码登录
\item 微信登录
\item 刷新token
\item 更改密码
\item 查找活动的审核人
\item 查找活动的发布人
\item 根据id查找用户
\item 根据账号（即手机号）查找用户
\item 修改用户信息(包括账号，不包括密码)
\item 注册用户信息
\item 为活动选择一个审核人
\item 绑定微信账号

\end{itemize}
\item RoleService

\begin{itemize}
\item 获取角色
\item 获取所有角色
\item 插入角色
\item 更新角色
\item 删除角色

\end{itemize}
\item UdrService

\begin{itemize}
\item 按照角色id获取角色
\item 按照用户id获取角色
\item 按照用户id获取角色名称
\item 为用户增加角色
\item 增加Udr
\item 保存所有Udr
\item 删除Udr
\item 删除所有Udr
\item 更新Udr

\end{itemize}
\item PictureService

  用于图片传输，如用户头像和活动图片的上传

\begin{itemize}
\item 返回用户头像
\item 返回活动图片
\item 上传用户头像
\item 上传活动图片

\end{itemize}
\item RsaService

  RSA加密算法解析

\begin{itemize}
\item 使用私钥进行解码

\end{itemize}
\end{itemize}
\subsubsection{Controller层}

见接口设计

